using System.Reflection;
using Gamov.Net6.Core.Helper;
using Gamov.Net6.Framework.Attributes;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;

var builder = new HostBuilder().ConfigureDefaults(args)
.ConfigureServices((hostContext, services) =>
{
    // 配置服务
    var types = Assembly.GetExecutingAssembly().GetTypes();
    var descriptors = new List<ServiceDescriptor>();
    var hostServiceTypes = new List<Type>();
    var optionTypes = new List<(Type, string)>();

    foreach (var type in types)
    {
        var attr = type.GetCustomAttribute<ComponentAttribute>();
        if (attr != null)
        {
            descriptors.Add(new ServiceDescriptor(attr.InterfaceType, type, attr.LifeTime));
        }

        var attr1 = type.GetCustomAttribute<HostServiceAttribute>();
        if (attr1 != null)
        {
            hostServiceTypes.Add(type);
        }

        var attr2 = type.GetCustomAttribute<OptionAttribute>();
        if (attr2 != null)
        {
            optionTypes.Add((type, attr2.RootName));
        }
    }

    foreach (var item in descriptors)
    {
        // 依赖注入
        services.Add(item);
    }

    foreach (var optionType in optionTypes)
    {
        // 反射绑定配置文件，等价于services.AddOptions<ServerConfig>().Bind(hostContext.Configuration.GetSection("Server"));
        var result = ReflectsHelper.OptionsServiceCollectionExtensions_AddOptions(optionType.Item1)
            .Invoke(services, new object[] { services });
        ReflectsHelper.OptionsBuilderConfigurationExtensions_Bind(optionType.Item1)
            .Invoke(result, new object[] { result, hostContext.Configuration.GetSection(optionType.Item2) });
    }

    foreach (var hostServiceType in hostServiceTypes)
    {
        // 反射获取hostservice, 等价于 services.AddHostedService<WebsocketServerHost>();
        ReflectsHelper.ServiceCollectionHostedServiceExtensions_AddHostedService(hostServiceType).Invoke(services, new object[] { services });
    }

    services.AddLogging(builder =>
    {
        builder.SetMinimumLevel(LogLevel.Trace);
        builder.AddNLog(hostContext.Configuration);
    });
}).UseConsoleLifetime();

await builder.Build().RunAsync();
